﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using ResourcesManager;
using System.Windows.Resources;

namespace BaseControls
{
    /// <summary>
    /// This class provide base class for any level for games.
    /// </summary>
    public class BaseLevel : Canvas
    {
        public BaseLevel()
        {         
            this.Loaded+=new RoutedEventHandler((obj,arg)=>{Refresh();});              
        }        
        /// <summary>
        /// Resources that will be download and load before scene is show.
        /// </summary>
        public static readonly DependencyProperty ResourcesNeededProperty = DependencyProperty.Register("ResourcesNeeded", typeof(string), typeof(BaseLevel), new PropertyMetadata(""));

        public string ResourcesNeeded
        {
            get
            {
                return (string)this.GetValue(ResourcesNeededProperty);
            }
            set
            {
                base.SetValue(ResourcesNeededProperty, value);
            }
        }
        public static readonly DependencyProperty BackgroundImageProperty = DependencyProperty.Register("BackgroundImage", typeof(string), typeof(BaseLevel), new PropertyMetadata(null));                        
        /// <summary>
        /// This Event is main game channel between engine and FrameControl.
        /// </summary>
        public event GameEventHandler GameEvent;
        private bool isItemListBuild = false;
        /// <summary>
        /// List of object that user have to find.
        /// </summary>
        protected Dictionary<object, string> ObjectList = new Dictionary<object, string>();        

        /// <summary>
        /// Event that is catch from Item element (in HOG game item is element to find).
        /// </summary>
        /// <param name="data">Data object</param>
        /// <param name="sender">Sender object that raise event.</param>
        /// <param name="arg">Arguments.</param>
        public virtual void OnItemComplete(object data, object sender, EventArgs arg)
        {
            if (GameEvent == null)
                return;            
        }
        /// <summary>
        /// Raise the event.
        /// </summary>
        /// <param name="data">Data that are </param>
        /// <param name="type"></param>
        protected void OnGameEvent(object data, GameChangeType type)
        {
            if(GameEvent != null)
                GameEvent(data, type);
        }
        /// <summary>
        /// This method is raised after finished level.
        /// </summary>
        /// <param name="data"></param>
        protected virtual void FinishLevel(object data)
        {

            OnGameEvent(data, GameChangeType.LevelComplete);
        }
        /// <summary>
        /// Method return Items to find in HOG level.
        /// </summary>
        /// <returns>List of Items to find in level</returns>
        public List<string> GetItems()        
        {
            if (!isItemListBuild)
            {
                BuildItems();
                isItemListBuild = true;
            }
            return ConvertDictionary(ObjectList);            
        }
        /// <summary>
        /// Build Items list by search scene and finding BaseItem objects.
        /// </summary>
        private void BuildItems()
        {
            Dictionary<object, string> tmp = new Dictionary<object, string>();
            foreach (UIElement item in this.Children)
            {
                BaseItem baseItem = item as BaseItem;
                if (baseItem != null && baseItem.Active)//dodać isActive oraz Scenario name
                    tmp.Add(baseItem, baseItem.ScenarioName);
            }
            ObjectList = tmp;
        }
        private List<string> ConvertDictionary(Dictionary<object,string> dictToMod)
        { 
            List<string> tmp = new List<string>();
            foreach (KeyValuePair<object, string> item in dictToMod)
                tmp.Add(item.Value);
            return tmp;
        }
        public string BackgroundImage
        {
            set
            {
                this.SetValue(BackgroundImageProperty, value);
            }
            get
            {
                return this.GetValue(BackgroundImageProperty) as string;
            }
        }
        public override void OnApplyTemplate()
        {                     
            base.OnApplyTemplate();
        }        
        public virtual void Refresh()
        {
            if(BackgroundImage != null)
            ResourcesManager.ResourcesManager.DownloadFile(new UriEx(new Uri((string)BackgroundImage, UriKind.Relative),this), (sender,stream) =>
            {
                if (stream != null)
                {
                    SetStream(stream);
                }
            }, null);            
        }
        public virtual void AssignStream(Stream stream)
        {
            SetStream(stream);
        }
        /// <summary>
        /// Method that is invoke by Resources Manager.
        /// </summary>
        /// <param name="stream">Stream that is downloaded</param>
        private void SetStream(Stream stream)
        {
            BitmapImage image = new BitmapImage();
            image.SetSource(stream);
            if (double.IsNaN(this.Width))
                this.Width = image.PixelWidth;
            if (double.IsNaN(this.Height))
                this.Height = image.PixelHeight;
            ImageBrush brush = new ImageBrush();
            brush.ImageSource = image;
            this.Background = brush;  
        }
        /// <summary>
        /// Main player for background music
        /// </summary>
        protected static MediaElement BackgroundMusicPlayer = null;
        /// <summary>
        /// Loading music for level
        /// </summary>
        /// <param name="uri"></param>
        private void LoadLevelMusic(string uri)
        {
            if (uri != null && uri != "")//start the music
            {
                BackgroundMusicPlayer = new MediaElement();
                BackgroundMusicPlayer.AutoPlay = false;
                StreamResourceInfo info = Application.GetResourceStream(new Uri(uri, UriKind.RelativeOrAbsolute));
                if (info != null)
                    BackgroundMusicPlayer.SetSource(info.Stream);
                else
                    BackgroundMusicPlayer.Source = new Uri(uri, UriKind.RelativeOrAbsolute);                                               
            }
        }
        /// <summary>
        /// This method start play music.
        /// </summary>
        public virtual void PlayMusic()
        {
            if (BackgroundMusicPlayer != null)
                BackgroundMusicPlayer.Play();
        }
        /// <summary>
        /// Stop playing actual background music
        /// </summary>
        public virtual void StopMusic()
        {
            if(BackgroundMusicPlayer != null)
                BackgroundMusicPlayer.Stop();
        }
        /// <summary>
        /// Update sound volume and other
        /// </summary>
        public virtual void UpdateMusic()
        {
        }
        /// <summary>
        /// Property that define music for level
        /// </summary>
        public static readonly DependencyProperty LevelMusicProperty = DependencyProperty.Register("LevelMusic", typeof(string), typeof(HogBaseLevel), null);

        public string LevelMusic
        {
            get
            {
                return (string)this.GetValue(LevelMusicProperty);
            }
            set
            {
                this.SetValue(LevelMusicProperty, value);
                LoadLevelMusic(value);
            }
        }
    }
}
